package hubsniffer;

import libjdc.dc.client.User;
import libjdc.dc.client.UserList;
import libjdc.dc.util.NoIPDupesComparator;
import libjdc.dc.util.NoNickDupesComparator;
import libjdc.dc.util.NoShareDupesComparator;
import libjdc.dc.util.PowerOfByte;
import libjdc.dc.log.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;

public class HubSnifferLog {
    
    public static HubSnifferLog getInstance(){
        try {
            return new HubSnifferLog();
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        }
    }
    
    
	
	private LinkedList<DCHub> hublist;
	private OutputStream out;
	private Date start;
	private long offset;

	public void printHubsFinal(LinkedList<DCHub> hs) throws IOException{
		println("Imprimir todos os hubs:");
		long usercount=0;
		long sharecount = 0;
		for(int i=0; i<hs.size();i++){
			println("\tAddress: "+hs.get(i).getHost()+":"+hs.get(i).getPort()+"\tusercount: "+hs.get(i).getHubSession().getUserList().size()+"\tsharecount: "+hs.get(i).getHubSession().getUserList().getUserShare());
			usercount +=hs.get(i).getHubSession().getUserList().size();
			sharecount +=hs.get(i).getHubSession().getUserList().getUserShare();
		}
		println("HubCount: "+hs.size()+"\tUserCount(total): "+usercount+"\tShare(Total): "+PowerOfByte.convert(sharecount)+" ("+sharecount+" Bytes)");
		println("User/Hub(Average): "+(usercount/hs.size())+"\tShare/user(Average): "+PowerOfByte.convert(sharecount/usercount)+" ("+(sharecount/usercount)+" Bytes)");
	}
	
	private void print(String message,Iterator<DCHub> hubIt,Comparator<User> c) throws IOException{
		UserList total = new UserList(c);
		int nHubs=0;
		while(hubIt.hasNext()){
			total.addAll((hubIt.next()).getHubSession().getUserList());
			nHubs++;
		}
		println(message+total.size()+"\tShare(Total): "+PowerOfByte.convert(total.getUserShare())+" ("+total.getUserShare()+" Bytes)");
		println("User/Hub(Average): "+(total.size()/nHubs)+"\tShare/user(Average): "+PowerOfByte.convert(total.getUserShare()/total.size())+" ("+(total.getUserShare()/total.size())+" Bytes)");
	}
	
	public HubSnifferLog() throws IOException{
            Log.out.println(Settings.getInstance().getHUBSNIFFERLOG_PATH());
		out = new FileOutputStream(Settings.getInstance().getHUBSNIFFERLOG_PATH()+File.separator+Settings.getInstance().getHUBSNIFFERLOG_FILE_NAME());
	}
        
        public HubSnifferLog(OutputStream out) throws IOException{
           this.out = out;
	}
	
	public void logHublist(LinkedList<DCHub> hublist,Date start, long offset) throws IOException{
		this.hublist = hublist;
		out = new FileOutputStream(Settings.getInstance().getHUBSNIFFERLOG_PATH()+File.separator+Settings.getInstance().getHUBSNIFFERLOG_FILE_NAME());
		this.start = start;
		this.offset = offset;
		openLogStream();
		printHubsFinal(hublist);
		closeLogStream();
	}
	public void log(String entry) throws IOException{
		println("<"+new Date()+"> "+entry);
	}
	
	private void openLogStream() throws IOException{
		println("-----------------------------------");
		println("Inicio de execu��o: "+start);
		println("Tempo de execu��o da simula��o: "+offset+" ms");
		println("-----------------------------------");
	}
	private void println(String s) throws IOException{
		write(s+"\n");
	}
	private void write(String s) throws IOException{
		out.write(s.getBytes(Settings.getInstance().getENCONDING()));
	}
	
	private void writeFinalInfo() throws IOException{
		println("-----------------------------------");
		print("UserCount(sem nicks repetidos): ",hublist.iterator(),new NoNickDupesComparator());
		println("-----------------------------------");
		print("UserCount(sem shares repetidos): ",hublist.iterator(),new NoShareDupesComparator());
		println("-----------------------------------");
		print("UserCount(sem ips repetidos): ",hublist.iterator(),new NoIPDupesComparator());
		
	}
	public void close() throws IOException{
		out.close();
	}
	
	public void closeLogStream() throws IOException{
		writeFinalInfo();
		out.close();
	}
}
